
package com.jf.cloud.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.jf.cloud.api.delivery.dto.DeliveryOrderItemDTO;
import com.jf.cloud.api.feign.SearchOrderFeignClient;
import com.jf.cloud.api.multishop.bo.EsShopDetailBO;
import com.jf.cloud.api.multishop.feign.ShopDetailFeignClient;
import com.jf.cloud.api.order.bo.DistributionAmountWithOrderIdBO;
import com.jf.cloud.api.order.bo.UserScoreLogOrderBO;
import com.jf.cloud.api.product.feign.CategoryFeignClient;
import com.jf.cloud.api.product.feign.SkuFeignClient;
import com.jf.cloud.api.product.util.ProductLangUtil;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.i18n.I18nMessage;
import com.jf.cloud.common.order.bo.EsOrderItemBO;
import com.jf.cloud.common.order.constant.DeliveryType;
import com.jf.cloud.common.order.constant.OrderActivityType;
import com.jf.cloud.common.order.constant.OrderType;
import com.jf.cloud.common.order.dto.OrderSearchDTO;
import com.jf.cloud.common.order.util.OrderLangUtil;
import com.jf.cloud.common.order.vo.*;
import com.jf.cloud.common.product.constant.PreSaleType;
import com.jf.cloud.common.product.vo.CategoryVO;
import com.jf.cloud.common.product.vo.SkuVO;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.util.LangUtil;
import com.jf.cloud.common.util.PriceUtil;
import com.jf.cloud.order.mapper.*;
import com.jf.cloud.order.model.Order;
import com.jf.cloud.order.model.OrderItem;
import com.jf.cloud.order.service.OrderItemService;
import com.jf.cloud.order.vo.OrderDetailVO;
import com.jf.cloud.order.vo.OrderItemDetailVO;
import com.jf.cloud.order.vo.OrderRefundVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单项
 *
 * @author zz
 * @date 2020-12-04 11:27:35
 */
@Service
public class OrderItemServiceImpl implements OrderItemService {
    private final Logger LOGGER = LoggerFactory.getLogger(OrderItemService.class);

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private OrderItemLangMapper orderItemLangMapper;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private ShopDetailFeignClient shopDetailFeignClient;
    @Autowired
    private OrderRefundMapper orderRefundMapper;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private SkuFeignClient skuFeignClient;

    @Autowired
    private OrderPreSaleInfoMapper orderPreSaleInfoMapper;

    @Autowired
    private SearchOrderFeignClient searchOrderFeignClient;


    @Override
    public PageVO<OrderItemVO> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> orderItemMapper.list());
    }

    @Override
    public OrderItemVO getByOrderItemId(Long orderItemId) {
        return orderItemMapper.getByOrderItemId(orderItemId, I18nMessage.getLang());
    }

    @Override
    public void save(OrderItem orderItem) {
        orderItemMapper.save(orderItem);
    }

    @Override
    public void update(OrderItem orderItem) {
        orderItemMapper.update(orderItem);
    }

    @Override
    public void deleteById(Long orderItemId) {
        orderItemMapper.deleteById(orderItemId);
    }

    @Override
    public List<OrderItem> listOrderItemsByOrderId(Long orderId) {
        return orderItemMapper.listOrderItemsByOrderId(orderId);
    }

    @Override
    public List<OrderItem> listOrderItemsByOrderIds(Long orderId) {
        return orderItemMapper.listOrderItemsByOrderIds(orderId);
    }

    @Override
    public List<OrderItemVO> listOrderItemAndLangByOrderId(Long orderId) {
        List<OrderItemVO> orderItems = orderItemMapper.listOrderItemAndLangByOrderId(orderId);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<DistributionAmountWithOrderIdBO> sumTotalDistributionAmountByOrderIds(List<Long> orderIds) {
        return orderItemMapper.sumTotalDistributionAmountByOrderIds(orderIds);
    }

    @Override
    public void saveBatch(List<OrderItem> orderItems) {
        if (CollUtil.isEmpty(orderItems)) {
            return;
        }
        for (OrderItem orderItem : orderItems) {
            orderItemMapper.save(orderItem);
        }
//        orderItemMapper.saveBatch(orderItems);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(List<OrderItem> orderItems) {
        for (OrderItem orderItem : orderItems) {
            orderItemMapper.update(orderItem);
        }
    }

    @Override
    public List<String> getSpuNameListByOrderIds(long[] orderIdList) {
        List<String> spuNameList = new ArrayList<>();
        List<OrderItemLangVO> orderItemLangList = orderItemLangMapper.getLangListByOrderIds(orderIdList);
        Map<Long, List<OrderItemLangVO>> orderItemLangMap = orderItemLangList.stream().collect(Collectors.groupingBy(OrderItemLangVO::getOrderItemId));
        for (Long orderItemId : orderItemLangMap.keySet()) {
            Map<Integer, String> spuNameMap = orderItemLangMap.get(orderItemId).stream().collect(Collectors.toMap(OrderItemLangVO::getLang, OrderItemLangVO::getSpuName));
            spuNameList.add(LangUtil.getLangValue(spuNameMap));
        }
        return spuNameList;
    }

    @Override
    public Integer countByOrderId(Long orderId) {
        return orderItemMapper.countByOrderId(orderId);
    }

    @Override
    public Integer sumNumByOrderId(Long orderId) {
        return orderItemMapper.sumNumByOrderId(orderId);
    }

    @Override
    public void updateByDeliveries(List<DeliveryOrderItemDTO> deliveryOrderItems, Integer deliveryType) {
        int devType = 0;
        for (DeliveryOrderItemDTO deliveryOrderItem : deliveryOrderItems) {
            devType = orderItemMapper.getDevTypeByOrderItemId(deliveryOrderItem.getOrderItemId());
            if (Objects.equals(devType, DeliveryType.DELIVERY.value())) {
                //如果快递项已有快递类型，则set进去应当是快递类型
                deliveryType = devType;
            }
            orderItemMapper.updateByDelivery(deliveryOrderItem, deliveryType);
        }
    }

    @Override
    public int countUnDeliveryNumByOrderId(Long orderId) {
        return orderItemMapper.countUnDeliveryNumByOrderId(orderId);
    }

    @Override
    public void reduceUnDeliveryNumByOrderItemId(Long orderItemId, Integer count) {
        orderItemMapper.reduceUnDeliveryNumByOrderItemId(orderItemId, count);
    }

    @Override
    public void updateRefundStatusByOrderId(Long orderId, Integer refundStatus) {
        orderItemMapper.updateRefundStatusByOrderId(orderId, refundStatus);
    }

    @Override
    public OrderDetailVO listDetailByParam(Long orderId, Long refundId) {
        OrderDetailVO orderDetailVO = new OrderDetailVO();
        Integer lang = I18nMessage.getLang();
        List<OrderItemDetailVO> list = orderItemMapper.listDetailByOrderId(orderId, lang);
        Order order = orderMapper.getByOrderId(orderId);
        OrderPreSaleInfoVO orderPreSaleInfoVO = orderPreSaleInfoMapper.getByOrderId(orderId);
        List<OrderItem> orderItems = orderItemMapper.listOrderItemsByOrderId(orderId);
        HashSet<Long> spuIdSet = new HashSet<>();
        orderItems.forEach(s -> spuIdSet.add(s.getSpuId()));
        List<Long> spuIds = new ArrayList<>(spuIdSet);
        List<SkuVO> skuVOList = skuFeignClient.listBySpuIds(spuIds).getData();
        List<Long> supplierSkuIdList = skuVOList.stream()
                .filter(sku -> sku.getSupplierSkuId() != null && sku.getSupplierSkuId() != 0)
                .map(SkuVO::getSupplierSkuId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(supplierSkuIdList)) {
            LOGGER.info("获取代销商品对应的供应商商品的sku信息，supplierSkuIdList:{}", supplierSkuIdList);
            List<SkuVO> supplierSkuVOList = skuFeignClient.getByIds(supplierSkuIdList).getData();
            Map<Long, Long> supplierSkuMap = supplierSkuVOList.stream().collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getPriceFee));
            Map<Long, Long> skuMap = skuVOList.stream()
                    .filter(sku -> sku.getSupplierSkuId() != null && sku.getSupplierSkuId() != 0)
                    .collect(Collectors.toMap(SkuVO::getSkuId, SkuVO::getSupplierSkuId));
            Map<Long, Long> itemIdMap = orderItems.stream().collect(Collectors.toMap(OrderItem::getOrderItemId, OrderItem::getSkuId));
            for (OrderItemDetailVO detailVO : list) {
                Long skuId = itemIdMap.get(detailVO.getOrderItemId());
                if (skuMap.containsKey(skuId)) {
                    detailVO.setSupplyPriceFee(supplierSkuMap.get(skuMap.get(skuId)));
                }
            }
        }
        handleOrderData(refundId, list, order, orderPreSaleInfoVO);

        ServerResponseEntity<EsShopDetailBO> shopDetailResponseEntity = shopDetailFeignClient.getShopByShopId(order.getShopId());
        LOGGER.info("获取店铺信息，shopDetailResponseEntity:{}", shopDetailResponseEntity);
        if (shopDetailResponseEntity.isFail()) {
            throw new LuckException(shopDetailResponseEntity.getMsg());
        }
        EsShopDetailBO shopDetailBO = shopDetailResponseEntity.getData();
        if (Objects.nonNull(shopDetailBO)) {
            orderDetailVO.setShopName(shopDetailBO.getShopName());
        }

        orderDetailVO.setOrderItemDetailList(list);
        orderDetailVO.setFreeFreightAmount(order.getFreeFreightAmount());
        orderDetailVO.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderDetailVO.setFreightAmount(order.getFreightAmount());
        return orderDetailVO;
    }

    private void handleOrderData(Long refundId, List<OrderItemDetailVO> list, Order order, OrderPreSaleInfoVO orderPreSaleInfoVO) {
        OrderRefundVO orderRefundVO = null;
        if (Objects.nonNull(refundId)) {
            orderRefundVO = orderRefundMapper.getByRefundId(refundId);
            LOGGER.info("获取退款单信息，orderRefundVO:{}", orderRefundVO);
        }
        for (OrderItemDetailVO detailVO : list) {
            if (Objects.equals(order.getOrderType(), OrderType.SECKILL.value())) {
                detailVO.setSeckillAmount(detailVO.getMultishopReduce());
            } else if (Objects.equals(order.getOrderType(), OrderType.GROUP.value())) {
                detailVO.setGroupAmount(detailVO.getMultishopReduce());
            }
            if (Objects.equals(order.getPreSaleType(), PreSaleType.DEPOSIT.value()) && Objects.equals(orderPreSaleInfoVO.getPayStatus(),1)) {
                // 平台佣金
                long platformCommission = PriceUtil.divideByBankerRounding((long) (orderPreSaleInfoVO.getDepositAmount() * detailVO.getRate()), 100);
                detailVO.setActualTotal(orderPreSaleInfoVO.getDepositAmount());
                detailVO.setPlatformCommission(platformCommission);
            }
            CategoryVO categoryVO = categoryFeignClient.getByCategoryId(detailVO.getCategoryId()).getData();
            LOGGER.info("获取商品分类信息，categoryVO:{}", categoryVO);
            if (Objects.nonNull(categoryVO)) {
                ProductLangUtil.category(categoryVO);
                detailVO.setCategoryName(categoryVO.getName());
            }
            if (Objects.nonNull(orderRefundVO) && Objects.equals(orderRefundVO.getOrderItemId(), 0L)) {
                detailVO.setRefundCount(detailVO.getCount());
                detailVO.setRefundAmount(detailVO.getActualTotal());
            } else if (Objects.nonNull(orderRefundVO) && !Objects.equals(orderRefundVO.getOrderItemId(), 0L)) {
                if (Objects.equals(orderRefundVO.getOrderItemId(), detailVO.getOrderItemId())) {
                    detailVO.setRefundCount(orderRefundVO.getRefundCount());
                    detailVO.setRefundAmount(orderRefundVO.getRefundAmount());
                }
                if(Objects.equals(detailVO.getActivityType(), OrderActivityType.GIVEAWAY.value())){
                    detailVO.setRefundCount(detailVO.getCount());
                }
            }
        }
    }

    @Override
    public OrderItemVO getSpuInfoByOrderItemId(Long orderItemId) {
        return orderItemMapper.getSpuInfoByOrderItemId(orderItemId, I18nMessage.getLang());
    }

    @Override
    public boolean getDevTypeByOrderId(Long orderId) {
        List<Integer> devTypes = orderItemMapper.getDevTypeByOrderId(orderId);
        return devTypes.contains(DeliveryType.DELIVERY.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatchDistributionAmount(List<EsOrderItemBO> message) {
        if (CollUtil.isEmpty(message)) {
            return;
        }
        int row = 0;
        for (EsOrderItemBO esOrderItemBO : message) {
            row += orderItemMapper.updateBatchDistributionAmount(esOrderItemBO);
        }

        if (row <= 0) {
            return;
        }
        // 将订单项里面的分销金额统计起来，加到订单的分销总金额里面
        List<Long> orderItemIds = message.stream().map(EsOrderItemBO::getOrderItemId).collect(Collectors.toList());
        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        orderSearchDTO.setOrderItemIds(orderItemIds);
        orderSearchDTO.setPageSize(orderItemIds.size());
        orderSearchDTO.setPageNum(1);
        ServerResponseEntity<List<EsOrderVO>> orderResponseEntity = searchOrderFeignClient.listOrder(orderSearchDTO);
        List<Order> updateOrders = new ArrayList<>();
        Map<Long, Long> amountMap = message.stream().collect(Collectors.toMap(EsOrderItemBO::getOrderItemId, EsOrderItemBO::getDistributionAmount));
        Map<Long, Long> parentAmountMap = message.stream().collect(Collectors.toMap(EsOrderItemBO::getOrderItemId, EsOrderItemBO::getDistributionParentAmount));
        for (EsOrderVO esOrderBO : orderResponseEntity.getData()) {
            List<EsOrderItemVO> items = esOrderBO.getOrderItems();
            Order update = new Order();
            update.setOrderId(esOrderBO.getOrderId());
            BigDecimal distributionAmount = new BigDecimal(BigInteger.ZERO.toString());
            for (EsOrderItemVO item : items) {
                if (amountMap.containsKey(item.getOrderItemId())) {
                    // 直推分销金额
                    distributionAmount = distributionAmount.add(new BigDecimal(amountMap.get(item.getOrderItemId()).toString()));
                    // 间推分销金额
                    if (Objects.nonNull(parentAmountMap.get(item.getOrderItemId())) && parentAmountMap.get(item.getOrderItemId()) >= 0) {
                        distributionAmount = distributionAmount.add(new BigDecimal(parentAmountMap.get(item.getOrderItemId()).toString()));
                    }
                }
            }
            update.setDistributionAmount(distributionAmount.longValue());
            updateOrders.add(update);
        }
        // 修改订单分销金额
        orderMapper.updateBatchDistributionAmount(updateOrders);
    }

    @Override
    public List<UserScoreLogOrderBO> getUserScoreLogDetail(List<Long> orderIds) {
        if (CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>();
        }
        return orderItemMapper.getUserScoreLogDetail(orderIds);
    }

    @Override
    public List<OrderItemVO> getOrderItemByGiveawayOrderItemId(Long userId, Long giveawayOrderItemId) {
        if (Objects.isNull(userId) || Objects.equals(giveawayOrderItemId, 0L)) {
            return new ArrayList<>();
        }
        List<OrderItemVO> orderItems = orderItemMapper.getOrderItemByGiveawayOrderItemId(userId, giveawayOrderItemId);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<OrderItemVO> getOrderItemByGiveawayOrderItemIds(List<Long> giveawayOrderItemIds, Long userId, Integer sysType) {
        List<OrderItemVO> orderItems = orderItemMapper.getOrderItemByGiveawayOrderItemIds(giveawayOrderItemIds, userId, sysType);
        OrderLangUtil.orderItemVOList(orderItems);
        return orderItems;
    }

    @Override
    public List<OrderItemVO> listOrderItemsByUserIdAndOrderIds(Long userId, List<Long> orderIds) {
        if (Objects.isNull(userId) || CollUtil.isEmpty(orderIds)) {
            return new ArrayList<>();
        }
        List<OrderItemVO> orderItemList = orderItemMapper.listOrderItemsByUserIdAndOrderIds(userId, orderIds);
        OrderLangUtil.orderItemVOList(orderItemList);
        return orderItemList;
    }

    @Override
    public List<OrderItem> listByIds(List<Long> itemIds) {
        return orderItemMapper.listByIds(itemIds);
    }
}
